#! /usr/local/bin/python
#-*- coding: utf-8 -*-

"""Sauvegarde des scores.

Les scores sont sauvegardés par niveau.
Les scores des parties personnalisées ne sont pas sauvegardés.
Par défaut seuls les 20 meuilleurs scores de chaques niveaux sont
sauvegardés.
"""

"""
Minesweeper 3K. Original implementation of the classic game of mines
for Python 3.
Copyright (C) 2010  Cedric Bonhomme

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

Minesweeper 3K  Copyright (C) 2010  Cedric Bonhomme
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
"""

__author__ = "Jerome Hussenet, Cedric Bonhomme"
__date__ = "$Date: 2010/02/27 $"
__copyright__ = "Copyright (c) 2010 Jerome Hussenet, Copyright (c) 2010 Cedric Bonhomme"
__license__ = "GPL 3"

class Personne(object):
    """Classe Personne

    Un joueur est caractérisé par son prénom
    et son temps.
    """
    def __init__(self):
        prenom = None
        temps = None

class Score(object):
    """Classe Score

    Permet de sauvegarder les scores selon les différents niveaux.
    """
    __currentNode__ = None
    __personneList__ = None

    def __init__(self):
        """Initialisation.

        self.maxScore permet de changer le nombre de highscores que l'on enregistre.
        """
        self.doc = None
        self.readXML()
        self.maxScore = 20

    def readXML(self, fichier = './sauvegarde/score.xml'):
        """Lit le fichier XML et crée l'instance "Document".
        """
        from xml.dom.minidom import parse
        try:
            self.doc = parse(fichier)
        except:
            pass

    def getRootElement(self):
        if self.__currentNode__ == None:
            self.__currentNode__ = self.doc.documentElement
        return self.__currentNode__

    def getPersonnes(self, modeJeux = 'debutant'):
        """Renvoie une liste de personnes.

        Renvoie la liste des personnes du highscore
        selon un certain niveau de jeux.
        """
        self.__personneList__ = []
        try:
            for personnes in self.doc.getElementsByTagName(modeJeux).item(0).childNodes:
                if personnes.nodeType == personnes.ELEMENT_NODE:
                    p = Personne()
                    try:
                        p.prenom = self.getText(personnes.getElementsByTagName("prenom")[0])
                        p.temps = self.getText(personnes.getElementsByTagName("temps")[0])
                    except:
                        print(_('Un des TAGs suivant est manquants : prenom, temps.'))
                    self.__personneList__.append(p)
        except: # pas encore de scores pour ce mode de jeux.
            pass
        return self.__personneList__

    def getText(self, node):
        return node.childNodes[0].nodeValue

    def testSiAjout(self, niveau, tempsPers):
        """Vérifie si l'ajout du score est possible.

        C'est-à-dire s'il n'y a pas déjà 20 scores (self.maxScore).
        Sinon si le nouveau score est meilleur que le plus mauvais,
        le plus mauvais sera remplacé par celui là.
        """
        liste = self.getPersonnes(niveau)
        listeDesPers = []
        listeDesScores = []

        for pers in liste:
            listeDesPers.append(pers.prenom)
            listeDesScores.append(int(pers.temps))

        if len(liste) >= self.maxScore:
            maxi = max(listeDesScores)
            if tempsPers < maxi:
                self.supprimePersonne(niveau, listeDesPers[listeDesScores.index(maxi)], maxi)
                self.write()
                return True
            else:
                return False
        else:
            return True

    def addPersonne(self, modePers, prenomPers, tempsPers):
        """Ajoute un nouveau score.

        Ajoute un score au fichier XML selon un temps et un score.
        """
        from xml.dom.minidom import Document

        try:
            racine = self.doc.getElementsByTagName('score').item(0)
        except:
            self.doc = Document()
            racine = self.doc.createElement("score")
            self.doc.appendChild(racine)

        personne = self.doc.createElement("personne")
        prenom = self.doc.createElement("prenom")
        temps = self.doc.createElement("temps")

        try:
            self.doc.getElementsByTagName(modePers).item(0).appendChild(personne)
        except:
            niveau = self.doc.createElement(modePers)
            racine.appendChild(niveau)
            niveau.appendChild(personne)

        prenom = self.doc.createElement("prenom")
        personne.appendChild(prenom)
        prenomText = self.doc.createTextNode(prenomPers)
        prenom.appendChild(prenomText)

        temps = self.doc.createElement("temps")
        personne.appendChild(temps)
        tempText = self.doc.createTextNode(tempsPers)
        temps.appendChild(tempText)

    def supprimePersonne(self, niveau, personne, temps):
        """Supprime un score.

        Prend en paramètre le niveau, le prénom et le temps
        du score à supprimer.
        Si deux éléments identiques existent, seul le premier
        est supprimé.
        """
        for score in self.doc.getElementsByTagName(niveau).item(0).childNodes:
            pers = self.getText(score.getElementsByTagName("prenom")[0])
            tmp = int(self.getText(score.getElementsByTagName("temps")[0]))
            if pers == personne and tmp == temps:
                while score.childNodes:
                    score.removeChild(score.firstChild)
                score.parentNode.removeChild(score)
                break

    def write(self, fichier = './sauvegarde/score.xml'):
        """Sauvegarde le fichier XML.
        """
        try:
            file = open(fichier, 'w')
            file.write('%s' % self.doc.toxml())
        except IOError as e:
            print(_("Erreur d'écriture :"), e)
        finally:
            file.close()

    def __str__(self):
        """Affichage élégant du fichier XML.
        """
        return self.doc.toprettyxml()


if __name__ == "__main__":
    # Tests :
    x = Score()
    x.addPersonne('debutant', 'Pierre', '20')
    x.addPersonne('debutant', 'Paul', '17')
    x.addPersonne('debutant', 'Jacques', '45')
    x.addPersonne('intermediaire', 'Luc', '20')
    x.addPersonne('expert', 'Didier', '20')
    x.addPersonne('expert', 'Roger', '12')
    print(x)
    #x.write()
    print('Scores niveau <<expert>> :')
    liste =  x.getPersonnes('expert')
    for gens in liste:
        print(gens.prenom, gens.temps)
    print("\n\n")
    print('Scores niveau <<debutant>> :')
    liste =  x.getPersonnes('debutant')
    for gens in liste:
        print(gens.prenom, gens.temps)